perm filename PARSE.DES[AL,HE] blob
sn#329156 filedate 1978-07-25 generic text, type C, neo UTF8
COMMENT ⊗ VALID 00016 PAGES
C REC PAGE DESCRIPTION
C00001 00001
C00003 00002
C00004 00003 ! statement, operator
C00010 00004 ! hash, check_entry, insert_entry
C00012 00005 ! ------- DECLARATIONS ----------
C00014 00006 ! ----- SYMBOL TABLE variables -----
C00018 00007 ! ----- SYMBOL TABLE EXTRACTION AND INSERTION FUNCTIONS -----
C00023 00008 ! ----- GET_TOKEN variables -----
C00025 00009 ! ----- FILE BOOKEEPING variables -----
C00026 00010 ! read,read_token,read_until,get_more_input
C00039 00011 ! read, push_macro_delimiters
C00050 00012 ! begin_P, end_P, open_paren_P
C00056 00013 ! declare_P
C00061 00014 ! open_P,close_P
C00066 00015 RECURSIVE PROCEDURE P_STATEMENT
C00071 00016 ! INITIALIZATION
C00072 ENDMK
C⊗;
comment ⊗
BEGIN
FLAGS: BAIL$ $D :debugging version
POINTY$ $P :pointy parser
AL$ $A :al parser
ALPOINTY$ =TRUE $B :used in both parsers
INITIALIZATION
P EXP
P STATEMENTS
END ⊗;
preload_array(name, defs, type, first, len)=[
preload_with defs null; type array name[first:first+len] ];
! N.B. -- preload_array always creates an array 1 longer than requested;
TYPES OF TESTS:
actual string
res_word &type_of_res_word
type_of_token
exp_type
exp_dimen
id_type
id
exp
id_type
exp_type
! statement, operator;
redefine xx(str,str2,str3,str4)=[
redefine index_count=index_count+1;
redefine id_count=id_count+1;
redefine xx_temp="define " & "str" & "_index=index_count";
redefine id_temp="define " & "str" & "_id=id_count";
xx_temp; id_temp;];
redefine yy(str,str2,str3,str)=[
redefine type_count=type_count+1;
redefine index_count=0;
redefine yy_temp="define " & "str" & "_type=type_count";
yy_temp;];
redefine zz(str,str2,str3,str4)=[
redefine class_count=class_count+1;
redefine type_count=0;
redefine index_count=0;
redefine zz_temp="define " & "str" & "_class=class_count";
zz_temp;];
define statement_definitions=[
ZZ(BLOCK)
YY(BEGIN, stlst, END)
YY(COBEGIN, stlst, COEND)
ZZ(END)
YY(END)
YY(COEND)
YY([;])
ZZ(STATEMENT)
YY(COMMENT)
XX(COMMENT, anything, )
YY(DECLARE)
XX(SCALAR, undlst)
XX(VECTOR, undlst)
XX(ROT, undlst)
XX(FRAME, undlst)
! XX(PLANE) ;
XX(TRANS, undlst)
XX(EVENT, undlst)
! XX(ATOM)
XX(WORLD)
XX(CM_LABEL)
XX(CLC_LABEL)
XX(CH_LABEL) ;
XX(LABEL, undlst)
YY(OPEN_PAREN)
XX([(], as-is, [)])
YY(GLOBAL)
YY(IF)
xx(IF, ae, THEN, st)
xx(IF, ae, THEN, st, ELSE, st)
YY(PLAN)
YY(WHILE)
XX(WHILE, se, DO, st)
YY(FOR)
xx(FOR, sc, ←, sce, STEP, sce, UNTIL, sce, DO, st)
YY(MOVE)
XX(VIA)
XX(WITH)
XX(APPROACH)
XX(ARRIVAL)
XX(DEPARTURE)
XX(MOVE, fr, TO, fre)
XX(MOVE, fr, TO, fre, clauses)
XX(OPEN, hn, TO, sce)
XX(CLOSE, hn, TO, sce)
XX(CENTER, ar)
XX(STOP, fr)
XX(WOBBLE)
YY(AFFIX, fr, TO, fr)
YY(UNFIX, fr, FROM, fr)
YY(SIGNAL)
XX(SIGNAL, ev)
XX(WAIT, ev)
YY(WHEN)
YY(DUMP)
XX(DUMP, idl)
YY(ASSERT)
XX(ASSERT)
XX(DENY)
YY(ON)
YY(DEFER)
! YY(REFERENCE) ;
YY(SPEED_FACTOR)
YY(DEFINE)
YY(REQUIRE)
XX(SOURCE_FILE)
XX(DELIMITERS)
XX(UNSTACK_DELIMITERS)
XX(REPLACE_DELIMITERS)
XX(MESSAGE)
XX(ERROR_MODES)
XX(COMPILER_SWITCHES)
XX(COMMENT_DELIMITERS)
XX(BAIL)
YY(DIMENSION)
XX(DIMENSION, ud, =, dimexp)
YY(UNIT)
YY(ABORT)
YY(PRINT)
YY(PAUSE)
XX(PAUSE, sce);
YY(NOTE)
XX(NOTE)
XX(NOTE1)
XX(NOTE2)
YY(ENABLE)
XX(ENABLE)
XX(DISABLE)
];
define operator_classes=[
ZZ(COMMA)
yy([,])
ZZ(OR)
yy([∨], or_X)
ZZ(AND)
yy([∧], and_X)
ZZ(NOT)
yy([¬], not_X)
ZZ(ORDER)
yy([=], seq_X)
yy([≠], sne_X)
yy([>], sgt_X)
yy([<], slt_X)
yy([≥], sge_X)
yy([≤], sle_X)
ZZ(ABS)
yy([|])
ZZ(EXP)
yy([+], plus_X)
yy([-], minus_X)
ZZ(FACTOR)
yy([.], vdot_X)
yy([*], times_X)
yy([/], sdiv_X)
yy(WRT, wrt_X)
ZZ(PF)
yy(→, →_X)
yy([↑], stos_X)
ZZ(FUNC)
yy([#],, nomv_X)
yy(ORIENT, orient_X)
yy(UNIT, uvect_X)
yy(AXIS, axis_X)
yy(POS, pos_X)
yy(INV, rinv_X)
ZZ(CLOSE_PAREN)
yy([)])
];
! All reserved word class id's have a postfix of "_RES". The fact that the parser
groups clases together is reflected by the definition of id's with "_beg" and
"_end" postfixes. The code demands that misc_RES be 0;
! hash, check_entry, insert_entry;
INTEGER PROCEDURE HASH(STRING S);
α INTEGER I,TOT,C;
C←LENGTH(S); TOT←0;
FOR I←1 STEP 1 UNTIL C DO TOT←TOT+I*LOP(S);
RETURN(TOT MOD HASHER);
β;
RPTR(SYMBOL) PROCEDURE CHECK_ENTRY(STRING S);
α RPTR(SYMBOL) S1;
S1←SYMBOL_BUCKET[SYMTAB_PTR←HASH(S)];
WHILE S1≠NULL_RECORD AND ¬EQU(S,SYMBOL:NAME[S1]) DO S1←SYMBOL:NEXT[S1];
RETURN(S1);
β;
RPTR(SYMBOL) PROCEDURE INSERT_ENTRY(STRING S, INTEGER S2(-1));
α RPTR(SYMBOL) S1;
IF S2≥0 THEN SYMTAB_PTR←HASH(S) ELSE SYMTAB_PTR←S2;
S1←NEW_RECORD(SYMBOL);
SYMBOL:NAME[S1]←S;
SYMBOL:NEXT[S1]←SYMBOL_BUCKET[SYMTAB_PTR];
SYMBOL:LAST[S1]←TOP_SYMBOL;
SYMBOL_TABLE[SYMTAB_PTR]←S1;
TOP_SYMBOL←S1;
RETURN(S1);
β;
! ------- DECLARATIONS ----------;
external integer
rpgsw;
IFC AL$ THENC
RPTR(file)
AL_file, ! current AL source file;
SEX_file, ! s-expression file;
BIN_file, ! PALX binary file;
ALL_file, ! ALC listing file;
LOG_file, ! LOG listing file;
NEW_file; ! new AL file for modified AL program;
ELSEC
RPTR(file)
PTY_file, ! collects terminal output;
READ_file, ! current readin file;
WRITE_file; ! current write file;
ENDC
BOOLEAN
AUTO_PROCEED, ! TRUE if auto_proceed switch is on for error fixup;
LOGGING, ! TRUE if errors to be logged;
COMPILE_LOGGING, ! TRUE if logging wanted trhough require statement;
LOG_FILE_OPEN, ! TRUE if there is a LOGGING file open;
STRICT_DIMEN_CHECK; ! TRUE if dimensions must be checked strictly;
INTEGER
CHANIN, ! current input channel number;
CHANSEX, ! sexfile channel number;
CHANLOG, ! channel of logging file;
CHANNEW; ! channel for new AL file;
IFC BAIL$ THENC
INTEGER
CHANTTYO; ! s-expression output on tty for examination;
ENDC
! ----- SYMBOL TABLE variables ----- ;
RCLASS
SYMBOL(
STRING
NAME;
RPTR(SYMBOL)
NEXT; ! points to next record with same hash key;
INTEGER
WORD1, ! keeps track of what type token this symbol is, e.g. macro,
reserved, id, etc.
WORD2; ! points to last declared SYMBOL record, used for deleting
declarations when exiting block;
IFC AL$ THENC
RPTR(DIMENS,MACRO)
PTR ! points to data record depending on what type
ELSEC of symbol;
RPTR(SCALAR,VECTOR,ROT,TRANS,FRAME)
PTR
ENDC
);
RPTR(SYMBOL) ARRAY
SYMBOL_BUCKET[0:hasher-1];
define
undeclared_token = 0,
id_token = 1,
reserved_token = 2,
macro_token = 3,
dimen_token = 4,
numeric_token = 5,
string_token = 6;
RPTR(SYMBOL)
LAST_SYMBOL_PTR;
INTEGER
SYMTAB_KEY; ! points to symbol table;
IFC AL$ THENC
RCLASS
DIMEN(
INTEGER
DISTANCE,
TIME,
FORCE,
ANGLE
);
RCLASS
PARAM_LIST(
STRING
PARAM, ! parameter itself;
DUMMY; ! internal parameter;
RPTR(PARAM_LIST)
NEXT ! pointer to next param_list record;
);
RCLASS
MACRO(
STRING
BODY;
INTEGER
DELIMITERS, ! two characters squeezed into this number;
NPARAMS;
RPTR(PARAM_LIST)
PARAM_PTR
);
ENDC
IFC POINTY$ THENC
RCLASS
SCALAR(
REAL
VALUE);
RCLASS
VECTOR(
REAL
X,
Y,
Z);
RCLASS
ROT(
REAL ARRAY
XF[1:5,1:4]);
RCLASS
FRAME(
STRING
NAME;
RPTR(FRAME)
DAD,
SON,
EBRO,
YBRO;
INTEGER
HOWLINKED;
REAL ARRAY
XF[1:5,1:4]);
RCLASS
TRANS(
STRING
NAME;
REAL ARRAY
XF[1:5,1:4]);
ENDC
! ----- SYMBOL TABLE EXTRACTION AND INSERTION FUNCTIONS -----;
! AL$ XXXX XXXXX XXXXX XXXX XXXXX
POINTY$ XXXX XXXXX XXXX XXXXX
NAME WORD1 WORD2 NEXT PTR PTR
RESERVED XXXX XXXXX XXXXX XXXX ---- -----
ID XXXX XXXXX XXXXX XXXX DIMEN SCALAR,VECTOR,ROT,FRAME
AL$ only
DIMEN XXXX XXXXX XXXXX XXXX DIMEN
MACRO XXXX XXXXX XXXXX XXXX MACRO
WORD1
0 1 2 3
0_1_2_3_4_5_6_7_8_9_0_1_2_3_4_5_6_7_8_9_0_1_2_3_4_5_6_7_8_9_0_1_2_3_4_5_
| LAST |TYPE | INDEX | CLASS | RESERVED
| LAST (8) |TYPE | INDEX | | FLAGS ID
| LAST (8) |TYPE | DIMEN
| LAST (8) |TYPE | | FLAGS MACRO
WORD2
0 1 2 3
0_1_2_3_4_5_6_7_8_9_0_1_2_3_4_5_6_7_8_9_0_1_2_3_4_5_6_7_8_9_0_1_2_3_4_5_
RESERVED
| FILE 5 | PAGE 7 | LINE 10 | ID
| FILE 5 | PAGE 7 | LINE 10 | DIMEN
| FILE 5 | PAGE 7 | LINE 10 | MACRO
define symbol_masks =(
xx(SYMBOL_LAST, 1, '776000000000, '2000000000)
xx(SYMBOL_TYPE, 1, '1600000000, '200000000)
xx(SYMBOL_INDEX,1, '174000000, '4000000)
xx(SYMBOL_CLASS,1, '3774000, '4000)
xx(SYMBOL_FLAGS,1, '3777, '2000)
xx(SYMBOL_FILE, 2, '760000000000, '20000000000)
xx(SYMBOL_PAGE, 2, '17700000000, '100000000)
xx(SYMBOL_LINE, 2, 77740000, '40000)
);
sym_mask_count=0;
redefine xx(str1,i1,i2,i3)=[
redefine sym_mask_count=sym_mask_count+1;
define str1=sym_mask_count];
symbol_masks;
define zap_sym(name,type,arg)=[
redefine xx(str1,i1,i2,i3) = [arg,];
preload_array(name,symbol_masks,type,1,sym_mask_count)];
zap_sym(sym_mask,integer,i2);
zap_sym(sym_mod,integer,i3);
INTEGER PROCEDURE GET(RPTR(SYMBOL) R1; INTEGER FIELD);
RETURN(IF FIELD≤SYMBOL_FLAGS
THEN ((SYMBOL:WORD1[R1] LAND SYM_MASK[FIELD])MOD SYM_MOD[FIELD])
ELSE ((SYMBOL:WORD2[R1] LAND SYM_MASK[FIELD])MOD SYM_MOD[FIELD]));
PROCEDURE PUT(RPTR(SYMBOL) R1; INTEGER FIELD,VALUE);
IF FIELD≤SYMBOL_FLAGS
THEN SYMBOL:WORD1[R1]←((SYMBOL:WORD1[R1] LAND LNOT SYM_MASK[FIELD])+VALUE*SYM_MOD[FIELD])
ELSE SYMBOL:WORD2[R1]←((SYMBOL:WORD2[R1] LAND LNOT SYM_MASK[FIELD])+VALUE*SYM_MOD[FIELD]);
PROCEDURE GET3(RPTR(R1); REFERENCE INTEGER TYPE,CLASS,INDEX);
α INTEGER WORD; WORD←SYMBOL:WORD1[R1];
TYPE ← (WORD LAND LNOT SYM_MASK[SYMBOL_TYPE])+VALUE*SYM_MOD[SYMBOL_TYPE];
CLASS← (WORD LAND LNOT SYM_MASK[SYMBOL_CLASS])+VALUE*SYM_MOD[SYMBOL_CLASS];
INDEX← (WORD LAND LNOT SYM_MASK[SYMBOL_INDEX])+VALUE*SYM_MOD[SYMBOL_INDEX];
β;
! ----- GET_TOKEN variables ----- ;
STRING
CURLINEP, ! amount of current line already parsed;
CURLINER, ! amount of current line remaining to be parsed;
CURLINE; ! current line: CURLINE = CURLINEP&TOKEN&CURLINER;
RCLASS
TOKEN(
STRING
TOKEN;
INTEGER
TYPE,
CLASS,
INDEX,
LEVEL;
IFC AL$ THENC
RPTR(DIMENS)
ELSEC
RPTR(SCALAR,VECTOR,ROT,TRANS,FRAME)
ENDC
PTR);
RPTR(TOKEN)
TOKENP;
! ----- ERROR RECOVERY flags ----- ;
BOOLEAN
MODIFY ! error may be modified by backing up;
MODIFIED; ! source code has been changed;
STRING
PARSED_STRING, ! string parsed but s-expression not output;
OUTSTRING; ! string of s-expression terms;
! ----- FILE BOOKEEPING variables ----- ;
RCLASS
FILEDATA(
integer
chn, comment channel on which file accessible;
fileno;
string
name,
ext,
ppn,
device,
def_ext;
boolean
out;
integer
mode, comment OPEN type info;
eof,
brchr,
count,
in_bfrs,
out_bfrs;
RPTR(FILEDATA)
next
);
RPTR(FILEDATA)
FILE_PTR,
FILE_PTR_HEAD;
! read,read_token,read_until,get_more_input;
TOKEN TOKEN_TYPE TOKEN_CLASS TOKEN_INDEX TOKEN_PTR
ID XXXXX ID_TOKEN XXXXXXX XXXXXXX
SCALAR_VALUE
VECTOR_VALUE
ETC
DIMEN XXXXX DIMEN_TOKEN XXXXXXX
RESERVED XXXXX RESERVED_TOKEN XXXXXXX XXXXXXX ???????
STATEMENT further subclass
OPERATOR
FUNCTION
MACRO XXXXX MACRO_TOKEN no. of args
substitution of macro parameters XX(A,B,C,etc)
→ XX(<bs>1<bs>A,<bs>2<bs>B,<bs>3<bs>C>)
TOKEN CLASSIFICATIONS:
alphabets a-z,A-Z 52
digits 0-9 10
underscore 1
delimiters cr,lf,tab,ff,sp,dquote,',` 8
relational ≤≥<>≠= 6
balanced pairs ()[]{}∩∪⊂⊃←→↑↓∧∨ 16
greek letters αβελπ∂ 6
single letters ↔∀∃!,?.;:∞/\@*⊗¬+|~%$≡∞ 25
non-E char bs,alt,vt,nul 4
total 128
PROCEDURE READ();
α
TOKEN_H←READ_TOKEN(NON_BLANK_BREAK,BRCHAR);
IF "A"≤BRCHAR≤"Z" OR "a"≤BRCHAR≤"z" OR BRCHAR="_"
THEN α TOKEN2←READ_TOKEN(ID_BREAK,BRCHAR);
IF (TOKEN_PTR←CHECK_ENTRY(TOKEN))≠NULL_RECORD
THEN α GET3(TOKEN_PTR,TOKEN_TYPE,TOKEN_CLASS,TOKEN_INDEX);
CASE TOKEN_TYPE OF
α
[reserved_TOKEN]
[dimen_TOKEN] ;
[id_TOKEN]
[macro_TOKEN]
IF MACRO:NPARAMS[DATA_PTR] = 0
THEN substitute for body
ELSE read real parameters;
β;
ELSE TOKEN_CLASS←undeclared_TOKEN;
β
ELSE IF "0"≤BRCHAR≤"9" OR BRCHAR="."
THEN TOKEN2←READ_TOKEN(NUMERIC_TOKEN,BRCHAR)
ELSE IF BRCHAR=DQUOTE
THEN TOKEN2←READ_TOKEN(STRING_TOKEN_BREAK,BRCHAR)
ELSE IF BRCHAR=COMMENT_OPEN_DELIMITER
THEN TOKEN2←READ_TOKEN(COMMENT_DELIMITER_BREAK,BRCHAR);
β;
STRING PROCEDURE READ_TOKEN(INTEGER BTABLE; REFERENCE INTEGER BRCHAR);
α STRING S1,S2;! s1 to be returned, s2 is processed part of string;
IF BTABLE=NON_BLANK_BREAK
THEN S1←S2←READ_UNTIL(BTABLE,BRCHAR)
ELSE IF BTABLE=ID_BREAK
THEN S1←S2←SCAN(CURLINER,ID_BREAK,BRCHAR)
ELSE IF BTABLE=NUMERIC_BREAK
THEN α INTEGER BRCHAR1,I1;
S1←S2←SCAN(CRULINER,NUMERIC_BREAM,BRCHAR);
I1←REALSCAN(S1,BRCHAR1);
IF S1=NULL
THEN α TOKEN_VALUE←I1; S2←S1; β
ELSE α CURLINER←S2&CURLINER;
S1←S2←LOP(CURLINER);
β;
β
ELSE IF BTABLE=DQUOTE_BREAK
THEN α S2←LOP(CURLINER);S1←S3←NULL;
WHILE CURLINER[1 TO 1]=DQUOTE
DO α S2←S1&DQUOTE&(S3←READ_UNTIL(DQUOTE,BRCHAR));
S2←S2&S3&LOP(CURLINER);
β;
β;
RETURN(S1);
β;
STRING PROCEDURE READ_UNTIL(INTEGER BTABLE, REFERENCE INTEGER BRCHAR);
α STRING S1;
S1←SCAN(CURLINER,BTABLE, BRCHAR);
WHILE BRCHAR=NULL AND ¬EOF
DO α GET_MORE_INPUT;
S1←S1&SCAN(CURLINER, BTABLE,BRCHAR);
β;
RETURN(S1);
β;
PROCEDURE GET_MORE_INPUT;
α IF CHANIN>-1 THEN CURLINE←CURLINER←INPUT(CHANIN,LF_FF_BREAK,BRCHAR);
IF CHANIN≤-1
THEN POP_MACRO
ELSE IF BRCHAR=LF
THEN LINENUM←LINENUM + 1
ELSE IF BRCHAR=FF
THEN α OUTSTR(NEWPAGE NUM); PAGENUM←PAGENUM+1; β
ELSE IF TOP_SOURCE≠NULL
THEN CLOSE_SOURCE
ELSE RETURN(NULL);
β;
! read, push_macro_delimiters;
INTEGER BRCHAR2;
STRING PROCEDURE KNVRT(STRING OLD_STR);
RETURN( SCAN(OLD_STR, KNVRT_BREAK, BRCHAR2));
STRING PROCEDURE READ(INTEGER BTABLE);
! RIGHT NOW THIS PROCEDURE IS KIND OF DUMB. IT'S INCLUDED IN THE HOPE
OF EVENTUALLY MAKING THE READING FACILITY MORE VERSATILE;
α STRING TEXT,TEXT2;
text ← SCAN(CURLINER,BTABLE,BRCHAR);
IF CHANIN > -1 THEN
IF (BTABLE=WORD_S_BREAK) OR (BTABLE=CLOSE_BRACE_BREAK) OR (BTABLE=QUOTE_BREAK)
OR (BTABLE=MACRO_DELIMITER_BREAK)
OR (BTABLE=OMIT_BREAK) OR (BTABLE=TTY_INPUT_BREAK)
THEN PARSED_STRING←PARSED_STRING&TEXT&BRCHAR
ELSE PARSED_STRING←PARSED_STRING&TEXT;
WHILE BRCHAR=0 DO
α BOOLEAN REPLACED;
REPLACED←TRUE;
IF CHANIN>-1 THEN α STRING CURR;
CURLINE←CURLINER←INPUT(CHANIN,lf_ff_break);
IF CHANTTYO≥0 THEN OUT(CHANTTYO, CURLINE);
macro_stack_top←macro_st2; macro_st2←null_record;β;
IF CHANIN≤-1 THEN
α "pop macro"
CHANIN←SOURCE_LIST:CHAN[TOP_SOURCE];
CURLINE←SOURCE_LIST:CUR_STRING[TOP_SOURCE];
CURLINER←SOURCE_LIST:CUR_STRINGR[TOP_SOURCE];
PAGENUM←SOURCE_LIST:PN[TOP_SOURCE];
LINENUM←SOURCE_LIST:LN[TOP_SOURCE];
macro_st2←SOURCE_LIST:macro_stack_TOP[TOP_SOURCE];
CURRENT_MACRO←SOURCE_LIST:CUR_MACRO[TOP_SOURCE];
TOP_SOURCE←SOURCE_LIST:NEXT[TOP_SOURCE];
IF (BTABLE=WORD_r_BREAK) OR (BTABLE=word_s_break) OR (BTABLE=non_digit_break)
then α brchar←space; return(text); β;
β "pop macro"
ELSE IF BRCHAR=lf THEN LINENUM←LINENUM+1
ELSE IF BRCHAR=ff THEN
α
outstr(" " & cvs((PAGENUM←PAGENUM+1)+1));
typed_page_num ← true; LINENUM←0
β
ELSE IF TOP_SOURCE≠NULL THEN
α "close_source"
printout;
RELEASE(CHANIN); RELEASE(CHANNEW);
IF EQU(FILE:DEVICE[PRESENT_FILE],"TTY") THEN RELEASE(CHANTTYO);
CURRENT_MACRO←NULL_RECORD;
MAC_NUM←SOURCE_LIST:NUM[TOP_SOURCE];
TOP_SOURCE←POP_SOURCE_LIST(TOP_SOURCE);
outstr(crlf); typed_page_num ← false; sourcelvl ← sourcelvl-1;
β "close_source"
ELSE IF EOF THEN
IF BLOCK_LEVEL > 1
THEN ERROR(500,"end of file encountered unexpectedly.")
ELSE RETURN(NULL);
TEXT2←SCAN(CURLINER,BTABLE,BRCHAR);
IF CHANIN>-1 THEN
IF (BTABLE=WORD_S_BREAK) OR (BTABLE=CLOSE_BRACE_BREAK) OR (BTABLE=QUOTE_BREAK)
OR (BTABLE=MACRO_DELIMITER_BREAK)
OR (BTABLE=OMIT_BREAK) OR (BTABLE=TTY_INPUT_BREAK)
THEN PARSED_STRING←PARSED_STRING&TEXT2&BRCHAR
ELSE PARSED_STRING←PARSED_STRING&TEXT2;
TEXT←TEXT&TEXT2;
β;
TOKEN2←TEXT;
ifc full_set thenc RETURN(knvrt(TEXT)); elsec RETURN(TEXT); ENDC
β;
! begin_P, end_P, open_paren_P;
RECURSIVE PROCEDURE BEGIN_P;
α INTEGER SAVE_DEC_NUM; RANY RR;
EXTERNAL RANY PROCEDURE $REC$(INTEGER OP; RANY R);
STRING B1,B2,E1,E2,TT; STRING S, BLK_NAME, BLK_NAME_END;
TT←"("&LABL;
B1←B2←"BEGIN";
E1←E2←"END";
BLOCK_LEVEL←BLOCK_LEVEL+1;
SAVE_DEC_NUM←DEC_NUM; DEC_NUM←0;
IF EQU(TOKEN,"BEGIN")
THEN α B2←"CO"&B2;E2←"CO"&E2;TT←TT&"BL";β
ELSE α B1←"CO"&B1;E1←"CO"&E1;TT←TT&"CO";β;
PRINT(TT); printout;
GET_TOKEN;
IF TOKEN_TYPE=STRING_TOKEN
THEN BLK_NAME←TOKEN
ELSE α BLK_NAME←NULL; REJECT←TRUE; β;
SPACING←SPACING+1;
WHILE ¬EQU(TOKEN,E1) DO
α
P_STATEMENT;
IF TYPE_OF_RES_WORD≠end_RES
THEN ERROR("Need semicolon before this token ⊂"&TOKEN&"⊃")
ELSE IF EQU(TOKEN,E2) THEN
α ERROR(5,"Block ends with " & E2 & crlf
& "Continue will view as "& E1);
TOKEN←E1;
β;
PRINTOUT;
β;
GET_TOKEN;
IF TYPE_OF_TOKEN=STRING_TOKEN
THEN BLK_NAME_END←TOKEN
ELSE α BLK_NAME_END←NULL; REJECT←TRUE; β;
SPACING←SPACING-1;
BLOCK_LEVEL←BLOCK_LEVEL-1;
IF ¬(EQU(BLK_NAME,BLK_NAME_END) OR EQU(BLK_NAME_END,NULL))
THEN ERROR(600, "Block name at end does not agree with that at beginning.");
FOR I←1 STEP 1 UNTIL DEC_NUM DO
α
SYMBOL_TABLE[HASH(SS←SYMBOL:NAME[TOP_SYMBOL],hasher)]
← SYMBOL:NEXT[TOP_SYMBOL];
TOP_SYMBOL←SYMBOL:LAST[RR←TOP_SYMBOL];
$REC$(5,RR);
β;
DEC_NUM←SAVE_DEC_NUM;
PRINT(")");
PRINTOUT;
β;
procedure end_P;
α ! SEMICOLON FOUND - NOOP;
REJECT←TRUE;
β;
procedure open_paren_P;
α INTEGER C; STRING TEMP;
! LEFT PAREN FOUND - STAIGHT TRANSFER;
C←1;
TEMP←"(";
WHILE C>0 DO
α
TEMP←TEMP&READ(paren_cr_break);
IF BRCHAR="(" THEN C←C+1
ELSE IF BRCHAR=")" THEN C←C-1 ELSE
α
PRINT(TEMP);
TEMP←NULL;
β;
β;
PRINT(TEMP);PRINTOUT;
β;
! declare_P;
procedure declare_P;
α
STRING BUILD_OUT; INTEGER DECLARATION_TYPE;
RPTR(DIMENS_EXPONENT)DIM;
DECLARATION_TYPE←TOKEN_INDEX;
IF DIM_PTR=NREC THEN
CASE SPECIAL_INFO OF
α
[scalar_VALUE]
[vector_VALUE] DIM←NIL_DIMENS;
[rot_VALUE] DIM←ANGLE_DIMENS;
[trans_VALUE]
[frame_VALUE] DIM←DISTANCE_DIMENS;
ELSE DIM←NULL_RECORD
β;
BUILD_OUT←"("&LABL&DEC_NAME[DECLARATION_TYPE]
GET_TOKEN;
DO α
CASE TOKEN_CLASS OF
α
[numeric_token] ERROR(XX,"TOKEN is numeric");
[string_token] ERROR(XX,"TOKEN is a string");
[reserved_token] ERROR(XX,"TOKEN is a reserved word");
[id_token]
IF TOKEN_LEVEL=BLOCK_LEVEL
THEN ERROR(XX,"TOKEN already declared on this block");
ELSE IF TOKEN_LEVEL=0
THEN ERROR(XX,"TOKEN is a predeclared constant.");
[undeclared_token] ;
ELSE ERROR(XX,"TROUBLE - shouldnt get here")
β;
BUILD_OUT←BUILD_OUT&" "&TOKEN;
P1←INSERT_ENTRY(TOKEN);
NEW_ID(DECLAR_TYPE,DIM_PTR);
GET_TOKEN;
IF EQU(TOKEN,",") THEN GET_TOKEN
ELSE IF ¬EQU(TOKEN,";") THEN ERROR_REJECT(7,"Missing comma.");
β UNTIL EQU(TOKEN,";");
PRINT(BUILD_OUT&" )");
β;
! open_P,close_P;
PROCEDURE open_P;
α STRING S,HAND; S←TOKEN;
GET_TOKEN;
IF ¬EQU(TOKEN,"BHAND") AND ¬EQU(TOKEN,"YHAND")
THEN ERROR("Need a hand after "&TOKEN);
ELSE HAND←TOKEN;
GET_TOKEN;
IF ¬EQU(TOKEN,"TO") THEN ERROR("Require TO here");
P_EXP;
CHECK_EXP_DIMENS_TYPE(DISTANCE_DIMENS," after "&S&" statement");
PRINT("( MO "&HAND&space4&OUTEXPR&" )");
β;
xx(IF)
xx(PLAN)
xx(WHILE)
xx(FOR)
xx(MOVE)
xx(AFFIX)
xx(UNFIX)
xx(SIGNAL)
xx(WAIT)
xx(WHEN)
xx(DUMP)
xx(ASSERT)
yy(DENY)
xx(ON)
yy(DEFER)
xx(CENTER)
xx(STOP)
xx(SPEED_FACTOR)
xx(DEFINE)
xx(REQUIRE)
xx(DIMENSION)
xx(COMMENT)
xx(ABORT)
yy(PRINT)
yy(PAUSE)
xx(NOTE)
yy(NOTE1)
yy(NOTE2)
xx(ENABLE)
xx(DISABLE)
];
define operator_classes=[
zz(COMMA)
yy([,])
xx(OR, or_X)
yy([∨], or_X)
xx(AND, and_X)
yy([∧], and_X)
xx(NOT, not_X)
yy([¬], not_X)
zz(ORDER)
yy([=], seq_X)
yy([≠], sne_X)
yy([>], sgt_X)
yy([<], slt_X)
yy([≥], sge_X)
yy([≤], sle_X)
zz(ABS)
yy([|])
yy(VVVTRANS)
zz(ADD)
yy([+], plus_X)
yy([-], minus_X)
zz(MULT)
yy([.], vdot_X)
yy([*], times_X)
yy([/], sdiv_X)
yy([⊗], vcross_X)
yy(WRT, wrt_X)
yy(VVROT, vvrot_X)
zz(TRANS)
yy(→, →_X)
yy([↑], stos_X)
zz(VECTOR)
yy([#],, nomv_X)
yy(ORIENT, orient_X)
yy(UNIT, uvect_X)
yy(AXIS, axis_X)
yy(POS, pos_X)
yy(INV, rinv_X)
! zz(SCALAR)
yy(ANGLE, angle_X);
zz(CLOSE_PAREN)
yy([)])
];
define require_definitions=[
xx(SOURCE_FILE)
xx(DELIMITERS)
xx(UNSTACK_DELIMITERS)
xx(REPLACE_DELIMITERS)
xx(MESSAGE)
xx(ERROR_MODES)
xx(COMPILER_SWITCHES)
xx(COMMENT_DELIMITERS)
xx(BAIL)
];
define move_definitions=[
xx(VIA)
xx(WITH)
xx(APPROACH)
yy(ARRIVAL)
yy(DEPARTURE)
xx(WOBBLE)
xx(DIRECTLY)
];
! All reserved word class id's have a postfix of "_RES". The fact that the parser
groups clases together is reflected by the definition of id's with "_beg" and
"_end" postfixes. The code demands that misc_RES be 0;
define
sex_RES =-2,
brace_RES =-1,
misc_RES =0,
cm_RES =0,
reserved_X_count=0,
statement_beg =reserved_X_count+1;
statement_definitions;
define
statement_end =reserved_X_count,
operator_beg =reserved_X_count+1;
operator_classes;
define
operator_end =reserved_X_count,
move_beg =reserved_X_count+1;
move_definitions;
define
move_end =reserved_X_count,
require_beg =reserved_X_count+1;
require_definitions;
define
require_end =reserved_X_count+1;
XX(METRIC) ! TIME, DISTANCE, etc.;
indices(require_definitions, _X);
indices(move_definitions, _X);
RECURSIVE PROCEDURE P_STATEMENT;
α "P_STATEMENT"
STRING LABL; RPTR DIM_PTR; LABEL RE_TRY; RE_TRY_0;
INTEGER SAVSPACING;
SAVSPACING←SPACING;
RE_TRY_0:
SPACING←SAVSPACING;
GET_TOKEN;
RE_TRY:
CASE TOKEN_TYPE OF
α
[string_TOKEN] ignore;
[undeclared_TOKEN]
α "undeclared token"
STRING TOKEN_SAVE,SS; TOKEN_SAVE←TOKEN; GET_TOKEN;
CASE TOKEN OF
α
["←"] α GET_TOKEN;
IF TOKEN = "←" THEN SS←SS&" PAS"
ELSE α SS←SS& " AS"; REJECT←TRUE; β;
P_EXP;
ERROR("UNDECLARED TOKEN "&TOKEN_SAVE&" WILL BE DECLARED "
&"A VARIABLE OF TYPE"&DATA_NAME[ID_TYPE]
&" DIMENSIONS PUT IN LATER");
MAKE_NEW_ID(TOKEN_SAVE,EXP_TYPE,EXP_DIMEN);
! ****** DECLARE TYPE HERE******;
PRINT("( "&LABL&SS); SPACING←SPACING + 1;
PRINT(OUTEXPR); SPACING←SPACING - 1;
PRINT(")");
β;
["<"] ERROR ("CHANGER NOT VALID YET");
[":"] α ERROR(TOKEN_SAVE&" WILL BE DECLARED A LABEL");
USED(MAKE_NEW_ID(TOKEN_SAVE,LABEL_TYPE));
GO_TO RE_TRY_0;
β;
ELSE ERROR("CANNOT HAVE "&TOKEN&" AFTER "&SS)
β;
[id_TOKEN]
IF ID_TYPE = LABEL_TYPE
THEN
α
IF UNUSED(TOKEN_PTR)
THEN α LABL ← LABL & TOKEN & " "; USED(TOKEN_PTR); β
ELSE ERROR("LABEL "&TOKEN&" HAS ALREADY BEEN USED");
IF ¬NEXT_TOKEN_EQU(":")
THEN ABORT("NEED COLON AFTER LABEL")
ELSE GOTO RE_TRY;
β
ELSE
α RPTR(ID) ID_PTR;
ID_PTR←TOKEN_PTR;SS←TOKEN; GET_TOKEN;
CASE TOKEN OF
α
["←"] α GET_TOKEN;
IF TOKEN = "←" THEN SS←SS&" PAS"
ELSE α SS←SS& " AS"; REJECT←TRUE; β;
P_EXP;
CHECK_EXP_TYPE(ID:TYPE[ID_PTR]);
CHECK_EXP_DIMEN(ID:DIMEN[ID_PTR]);
PRINT("( "&LABL&SS); SPACING←SPACING + 1;
PRINT(OUTEXPR); SPACING←SPACING - 1;
PRINT(")");
β;
["<"] ERROR ("CHANGER NOT VALID YET");
ELSE ERROR("CANNOT HAVE "&TOKEN&" AFTER "&SS)
β;
β;
[numeric_TOKEN]
ERROR("STATEMENT CANNOT BEGIN WITH A NUMERIC CONSTANT");
[dimen_TOKEN]
α DIM_PTR←TOKEN_PTR; GET_TOKEN;
IF ¬EQU(TOKEN,"SCALAR") OR ¬EQU(TOKEN,"VECTOR") OR ¬EQU(TOKEN,"TRANS")
THEN
ERROR("ONLY SCALARs, VECTORs,or TRANSes MAY BE DECLARED WITH DIMENSIONS")
ELSE DECLARE_P;
β;
[reserved_TOKEN]
IF (statement_beg ≤ TYPE_OF_RES_WORD ≤ statement_end)
THEN CASE TYPE_OF_RES_WORD - statement_beg OF
α
statement_definitions;
β
ELSE ERROR("STATEMENT CANNOT BEGIN WITH RESERVED WORD "&TOKEN);
ELSE ERROR("PARSER ERROR, SEND MESSAGE TO MSM");
β
β "P_STATEMENT";
! INITIALIZATION;
READ IN RESERVED WORDS TABLE;
READ IN PREDEFINED MACROS
READ IN PREDEFINED CONSTANTS;